package com.usian.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.common.dtos.PageResponseResult;
import com.usian.model.common.dtos.ResponseResult;
import com.usian.model.common.enums.AppHttpCodeEnum;
import com.usian.model.media.dtos.WmNewsDto;
import com.usian.model.media.dtos.WmNewsPageReqDto;
import com.usian.model.media.pojos.*;
import com.usian.utils.threadlocal.WmThreadLocalUtils;
import com.usian.wemedia.mapper.WmMaterialMapper;
import com.usian.wemedia.mapper.WmNewsMapper;
import com.usian.wemedia.mapper.WmNewsMaterialMapper;
import com.usian.wemedia.mapper.WmUserMapper;
import com.usian.wemedia.service.WmNewsService;
import com.usian.wemedia.service.WmUserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews>
        implements WmNewsService {

    @Value("${fileServerUrl}")
    private String fileServerUrl;

    @Autowired
    KafkaTemplate kafkaTemplate;

    @Autowired
    WmMaterialMapper wmMaterialMapper;

    @Autowired
    WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    WmNewsMapper wmNewsMapper;

    @Autowired
    WmUserService wmUserService;


    public static final Short COLLECT_MATERIAL = 1;//收藏
    public static final Short CANCEL_COLLECT_MATERIAL = 0;//收藏
    public static final String WM_NEWS_TYPE_IMAGE = "image"; //文本中的图片
    public static final Short WM_NEWS_NONE_IMAGE = 0;       //没有图片的
    public static final Short WM_NEWS_SINGLE_IMAGE = 1;     //一张图片的
    public static final Short WM_NEWS_MANY_IMAGE = 3;       //三张图片的
    public static final Short WM_NEWS_TYPE_AUTO = -1;       //自动的
    public static final Short WM_CONTENT_REFERENCE = 0;
    public static final Short WM_COVER_REFERENCE = 1;
    public static final short WM_NEWS_CONTENT_REFERENCE = 1;//主图引用


    /**
     * 内容列表查询
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findPage(WmNewsPageReqDto dto) {
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //查询当前登录用户信息
        WmUser wmUser = WmThreadLocalUtils.getUser();
        if (wmUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        LambdaQueryWrapper<WmNews> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        //状态查询
        if (dto.getStatus() != null) {
            lambdaQueryWrapper.eq(WmNews::getStatus, dto.getStatus());
        }

        //关键字查询
        if (dto.getKeyword() != null) {
            lambdaQueryWrapper.like(WmNews::getTitle, dto.getKeyword());
        }

        //频道查询
        if (dto.getChannelId() != null) {
            lambdaQueryWrapper.eq(WmNews::getChannelId, dto.getChannelId());
        }

        //时间区间查询
        if (dto.getBeginPubDate() != null && dto.getEndPubDate() != null) {
            lambdaQueryWrapper.between(WmNews::getCreatedTime, dto.getBeginPubDate(), dto.getEndPubDate());
        }

        lambdaQueryWrapper.eq(WmNews::getUserId, wmUser.getId());

        //倒序排序
        lambdaQueryWrapper.orderByDesc(WmNews::getCreatedTime);


        Page page = new Page(dto.getPage(), dto.getSize());
        IPage result = page(page, lambdaQueryWrapper);

        PageResponseResult responseResult = new PageResponseResult(dto.getPage(),
                dto.getSize(), (int) result.getTotal());
        responseResult.setData(result.getRecords());
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }


    /**
     * 发布文章
     *
     * @param dto
     * @param isSubmit
     * @return
     */
    @Override
    public ResponseResult submitNews(WmNewsDto dto, Short isSubmit) {
        //参数校验
        if (dto == null || StringUtils.isBlank(dto.getContent())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (isSubmit == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //解析wmnews表
        WmNews wmNews = new WmNews();
        //数据拷贝  浅拷贝
        BeanUtils.copyProperties(dto, wmNews);
        if (WM_NEWS_TYPE_AUTO.equals(dto.getType())) {   //封面图片自动的
            wmNews.setType(null);
        }
        //判断封面图片是否存在，若在则转换图片
        if (dto.getImages() != null && dto.getImages().size() > 0) {
            String s = dto.getImages().toString().replace("[", "").replace("]", "")
                    .replace(fileServerUrl, "").replace(" ", "");
            wmNews.setImages(s);
        }

        //保存数据  当前时间、当前登录操作用户的id
        wmNews.setCreatedTime(new Date());
        Integer id = WmThreadLocalUtils.getUser().getId();
        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        wmNews.setUserId(id);
        if (wmNews.getId() == null) {
            this.save(wmNews);
        } else {
            this.updateById(wmNews);
            QueryWrapper<WmNewsMaterial> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(WmNewsMaterial::getNewsId, wmNews.getId());
            wmNewsMaterialMapper.delete(queryWrapper);
        }


        //维护wmMaterial表
        String content = dto.getContent();   //获取文本内容
        List<Map> list = JSON.parseArray(content, Map.class);  // JSON转集合
        //提取文本中的图片
        List<String> imageList = this.ExtractImage(list);

        //判断isSubmit状态是否等于1并且长度大于0   保存文本中图片和素材表的关系
        if (isSubmit == WmNews.Status.SUBMIT.getCode() && imageList.size() > 0) {
            ResponseResult result = this.PreservationRelationship(imageList, wmNews.getId());

            if (result.getCode() != 0) {
                return result;
            }
        }

        //设置封面
        if (isSubmit.equals(WmNews.Status.ADMIN_AUTH.getCode())) {
            ResponseResult result = CoverAndImage(dto, imageList, wmNews);
            if (result.getCode() != 0) {
                return result;
            }
        }

        //保存完文章向kafka ，发送一个文章的id
        kafkaTemplate.send("wemediaAutoScan",wmNews.getId());

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    //提取封面图片且维护与素材表的关系
    private ResponseResult CoverAndImage(WmNewsDto dto, List<String> imageList, WmNews wmNews) {
        //判断图片个数
        List<String> imageListNew = new ArrayList<>();
        if (dto.getType().equals(WM_NEWS_TYPE_AUTO)) {
            //判断图片数量 ,大于1小于2,图片数量为1
            if (dto.getType() > 1 && dto.getType() <= 2) {
                wmNews.setType(WM_NEWS_SINGLE_IMAGE);
                imageListNew = imageList.stream().limit(1).collect(Collectors.toList());
            } else if (dto.getType() > 2) {   //大于2图片数量为3
                wmNews.setType(WM_NEWS_MANY_IMAGE);
                imageListNew = imageList.stream().limit(3).collect(Collectors.toList());
            } else {
                wmNews.setType(WM_NEWS_NONE_IMAGE);   //没图片，无图
            }
        }
        String str = null;
        //转换imageListNew集合的图片
        if (imageListNew.size() > 0) {
            str = imageListNew.toString().replace("[", "")
                    .replace("]", "").replace(fileServerUrl, "")
                    .replace(" ", "");

            wmNews.setImages(str);
        }
        this.updateById(wmNews);
        //维护封面图片和素材的关系
        List<String> imageListNew1 = new ArrayList<>();
        for (String s : imageListNew) {
            imageListNew1.add(s.replace(fileServerUrl, ""));
        }

        ResponseResult responseResult = this.PreservationRelationship(imageListNew1, wmNews.getId());
        return responseResult;
    }


    //保存文本中图片和素材表的关系
    private ResponseResult PreservationRelationship(List<String> imageList, Integer id) {
        //判断提取出来的图片是否存在在素材库
        LambdaQueryWrapper<WmMaterial> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(WmMaterial::getUrl, imageList);
        WmUser wmUser = WmThreadLocalUtils.getUser();
        if (wmUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        lambdaQueryWrapper.eq(WmMaterial::getUserId, wmUser.getId());
        List<WmMaterial> materialList = wmMaterialMapper.selectList(lambdaQueryWrapper);
        //把与素材有关的图片提取，存入wmMaterialListNews集合
        List<String> wmMaterialListNews = new ArrayList<>();
        if (materialList.size() > 0) {
            //取materialList中 url和id 封装成map集合 key：url    value：id
            Map<String, Integer> map = materialList.stream().
                    collect(Collectors.toMap(WmMaterial::getUrl, WmMaterial::getId));
            //二次遍历 imageList 集合中的数据  找出集合中的废数据
            for (String s : imageList) {
                Integer url = map.get(s);  //素材id
                if (url == null) {
                    return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
                } else {
                    wmMaterialListNews.add(url.toString());
                }
            }
        }
        //保存中间表
        wmNewsMaterialMapper.saveRelationsByContent(wmMaterialListNews, id, WM_NEWS_CONTENT_REFERENCE);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    //提取文本中的图片
    private List<String> ExtractImage(List<Map> list) {
        //定义存储文本中图片的集合
        ArrayList<String> imagesList = new ArrayList<>();
        for (Map map : list) {
            if (map.get("type").equals("image")) {
                String image = map.get("value").toString();
                String s = image.replace(fileServerUrl, "");  //转换图片
                imagesList.add(s);
            }
        }
        return imagesList;
    }


    /**
     * 根据id查询修改的数据，返回修改数据
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult findByNewId(Integer id) {
        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        WmNews wmNews = this.getById(id);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        ResponseResult responseResult = ResponseResult.okResult(wmNews);
        responseResult.setHost(fileServerUrl);
        return responseResult;
    }

    @Override
    public ResponseResult delByNewId(Integer id) {
        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        WmNews wmNews = this.getById(id);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //判断文章是否上架的状态 9:上架  1:下架
        if (wmNews.getStatus().equals(9) && wmNews.getEnable() == 1) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        QueryWrapper<WmNewsMaterial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNewsMaterial::getNewsId, wmNews.getId());
        wmNewsMaterialMapper.delete(queryWrapper);

        this.removeById(id);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 修改文章上下架
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //查询文章
        WmNews wmNews = this.getById(dto.getId());
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        if (wmNews.getStatus()!=9) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "文章已上架");
        }

        if (dto.getEnable() != null && (dto.getEnable() == 1 || dto.getEnable() == 0)) {
            this.update(Wrappers.<WmNews>lambdaUpdate().eq(WmNews::getId,dto.getId()).
                    set(WmNews::getEnable,dto.getEnable()));

            //发kafka，通知文章上下架
            Map<String, Object> map = new HashMap<>();
            map.put("enable",dto.getEnable());
            map.put("articleId",wmNews.getArticleId());
            kafkaTemplate.send("newsDownOrUp",JSON.toJSONString(map));

        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult updateByStatus(WmNews wmNews) {
        if (wmNews==null && wmNews.getId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        boolean b = update(Wrappers.<WmNews>lambdaUpdate().set(WmNews::getStatus, wmNews.getStatus())
                .set(WmNews::getArticleId, wmNews.getArticleId())
                .set(WmNews::getReason, wmNews.getReason())
                .eq(WmNews::getId, wmNews.getId()));

//        boolean b = this.updateById(wmNews);

        if (b){
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }else {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
    }

    @Override
    public List<Integer> findNews() {
        List<WmNews> list = list(Wrappers.<WmNews>lambdaQuery().
                eq(WmNews::getStatus, 8).lt(WmNews::getPublishTime,new Date()));

        List<Integer> resultList =
                list.stream().map(WmNews::getId).collect(Collectors.toList());

        return resultList;
    }

    @Override
    public ResponseResult findList(NewsAuthDto dto) {

        dto.checkParam();
        dto.setPage((dto.getPage()-1)*dto.getSize());
        List<WmNewsVo> list = wmNewsMapper.findList(dto);
        int count = wmNewsMapper.findCount(dto);

        PageResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), count);
        responseResult.setData(list);
        return responseResult;
    }

    @Override
    public WmNewsVo findWmNewsVo(Integer id) {
        if (id==null){
            return null;
        }

        WmNews wmNews = this.getById(id);
        WmUser wmUser =null;
        if (wmNews!=null && wmNews.getUserId()!=null){
             wmUser = wmUserService.getById(wmNews.getUserId());
        }

        WmNewsVo wmNewsVo = new WmNewsVo();
        BeanUtils.copyProperties(wmNews,wmNewsVo);
        wmNewsVo.setAuthorName(wmUser.getName());
        return wmNewsVo;
    }


}
